package net.teamclerks.rpgf.avatar;

import net.teamclerks.rpgf.script.action.Action;
import net.teamclerks.rpgf.script.director.Director;

/**
 * Avatars encompass every interactable player/object in the RPGF
 * world. Chests are a type of Avatar, the playable characters are
 * a type of Avatar, the NPCs are Avatars, etc. Everything interesting
 * happens between Avatars (outside the scope of battle and/or cutscenes).
 * <br/>
 * <br/>
 * IMPORTANT - By default, all Avatars have an anonymous Action
 * associated with them at the time of construction which are
 * entirely impotent. Calling <code>doAction</code> against an Avatar
 * without explicitly setting that Avatar's Action will do nothing,
 * though the call will succeed.
 * @author msmith
 *
 */
public abstract class Avatar
{
  /// DATAPOINTS ///
  /**
   * The unique identifier used to distinguish one avatar from another.
   */
  protected long id;
  /**
   * The name of this Avatar. Could be the character's name, 
   * could be null, could be "treasure_chest_51".
   */
  protected String name;
  /**
   * Whether this Avatar should obstruct other Avatars' movement.
   * True by default, there are few Avatars which should NOT obstruct
   * Avatar movement. An example of one use of this would be a DoorAvatar
   * in fancier implementations; the door would be obstructing until
   * it is opened, then its obstructing would be set to false.
   */
  protected boolean obstructing;
  
  
  /// CONTROL DATA ///
  /**
   * Whether this Avatar is under the user's control. Default <code>false</code>.
   */
  protected boolean userControlled;
  /**
   * The Action that this Avatar can take. Multiple Actions can be chained
   * together by setting <code>action.setChainedTo(Action)</code>. 
   */
  protected Action action;
  /**
   * Reference to the system's Director.
   */
  protected Director director;

  /// DENY CONSTRUCTOR ///
  private Avatar(){}
  
  /// PUBLIC CONSTRUCTOR ///
  /**
   * Public constructor.
   * @param director
   */
  public Avatar(Director director)
  {
    this();
    this.director = director;
    this.userControlled = false;
    this.obstructing = true;
    this.action = new Action(this.director)
    {
      @Override public void act(){}
    };
  }
  
  /// PUBLIC METHODS ///
  /**
   * Gets this Avatar's id.
   * @return id
   */
  public final long getId()
  {
    return id;
  }
  
  /**
   * Gets this Avatar's name.
   * @return name
   */
  public final String getName()
  {
    return name;
  }
  /**
   * Gets this Avatar's Action.
   * @return action
   */
  public final Action getAction()
  {
    return action;
  }
  /**
   * Sets this Avatar's Action.
   * @param action
   */
  public final void setAction(Action action)
  {
    this.action = action;
  }
  /**
   * Gets whether this Avatar obstructs the movement of other Avatars.
   * @return obstructing
   */
  public final boolean isObstructing()
  {
    return this.obstructing;
  }
  /**
   * Sets whether this Avatar should obstruct other Avatars' movement.
   * @param obstructing
   */
  public final void setObstructing(boolean obstructing)
  {
    this.obstructing = obstructing;
  }
  
  /**
   * Tells an Avatar that this Avatar is acting upon it and
   * the recipient should fire his act method.
   * @param recipient
   */
  public final void act(Avatar recipient)
  {
    if(recipient != null && recipient.getAction() != null)
    {
      recipient.getAction().setActor(this);
      recipient.getAction().setRecipient(recipient);
      recipient.getAction().doAction();
    }
  }
}